package cn.jtool.dig.server.service.impl;

import cn.jtool.dig.common.model.Session;
import cn.jtool.dig.common.netty.SessionManager;
import cn.jtool.dig.server.dao.entity.PortMapping;
import cn.jtool.dig.server.dao.entity.License;
import cn.jtool.dig.server.dao.repository.PortMappingRepository;
import cn.jtool.dig.server.dao.repository.LicenseRepository;
import cn.jtool.dig.server.domain.reqeust.LicenseParams;
import cn.jtool.dig.server.domain.reqeust.LicenseQueryRequest;
import cn.jtool.dig.server.domain.response.LicenseDetailResponse;
import cn.jtool.dig.server.domain.response.LicenseListResposne;
import cn.jtool.dig.server.service.LicenseService;
import cn.jtool.knife.core.result.PageResultEntity;
import cn.jtool.knife.core.result.ResultEntity;
import cn.jtool.knife.core.util.AssertUtil;
import cn.jtool.knife.core.util.IdUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

@Slf4j
@Service
public class LicenseServiceImpl implements LicenseService {


    @Resource
    private LicenseRepository licenseRepository;

    @Resource
    private PortMappingRepository portMappingRepository;

    @Override
    public void create(LicenseParams entity) {
        License license = this.licenseRepository.findOne(
                Example.of(License.builder().licenseName(entity.getLicenseName()).build())
        ).orElse(null);
        AssertUtil.checkNotNull(license, "授权码名称已存在");

        license = License.builder()
                .licenseName(entity.getLicenseName())
                .licenseKey(IdUtil.simpleUUID())
                .enableState(entity.getEnableState())
                .effectiveTime(entity.getEffectiveTime())
                .expireTime(entity.getExpireTime())
                .whiteIps(entity.getWhiteIps())
                .blackIps(entity.getBlackIps())
                .notes(entity.getNotes())
                .createTime(new Date())
                .updateTime(new Date())
                .build();
        this.licenseRepository.save(license);
    }

    @Override
    public void delete(Integer id) {
        License license = this.licenseRepository.findById(id).orElse(null);
        if(Objects.nonNull(license)){
            List<PortMapping> portMappings = this.portMappingRepository.findAll(
                    Example.of(PortMapping.builder().licenseKey(license.getLicenseKey()).build())
            );
            AssertUtil.checkNotEmpty(portMappings, "授权码正在使用中, 无法删除");
            this.licenseRepository.delete(license);
        }
    }

    @Override
    public void delete(Iterable<? extends Integer> integers) {

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Integer integer, Boolean isForce) {
        License license = this.licenseRepository.findById(integer).orElse(null);
        if(Objects.nonNull(license)){
            this.licenseRepository.delete(license);
            this.portMappingRepository.delete(
                    PortMapping.builder().licenseKey(license.getLicenseKey()).build()
            );
        }
    }

    @Override
    public PageResultEntity<LicenseListResposne> listByPage(LicenseQueryRequest params, int page, int limit) {
        PageHelper.startPage(page, limit);
        List<License> licenses = this.licenseRepository.findAll();
        PageInfo<License> pageInfo = new PageInfo<License>(licenses);
        List<LicenseListResposne> list = pageInfo.getList().stream().map(e -> {
            LicenseListResposne listResposne = LicenseListResposne.builder()
                    .id(e.getId())
                    .licenseName(e.getLicenseName())
                    .licenseKey(e.getLicenseKey())
                    .onlineState(0)
                    .enableState(e.getEnableState())
                    .effectiveTime(e.getEffectiveTime())
                    .expireTime(e.getExpireTime())
                    .createTime(e.getCreateTime()).build();
            Session session = SessionManager.getSession(e.getId());
            if(Objects.nonNull(session) && session.isConnect()){
                listResposne.setOnlineState(1);
            }
            return listResposne;
        }).toList();

        return PageResultEntity.<LicenseListResposne>builder().page(pageInfo.getPageNum()).limit(pageInfo.getPageSize()).pages(pageInfo.getPages())
                .total(pageInfo.getTotal()).items(list).build();
    }

    @Override
    public LicenseDetailResponse selectOne(Integer id) {
        License license = this.licenseRepository.findById(id).orElse(null);
        AssertUtil.checkNull(license, "授权码不存在");
        return LicenseDetailResponse.builder()
                .id(license.getId())
                .licenseName(license.getLicenseName())
                .licenseKey(license.getLicenseKey())
                .enableState(license.getEnableState())
                .effectiveTime(license.getEffectiveTime())
                .expireTime(license.getExpireTime())
                .whiteIps(license.getWhiteIps())
                .blackIps(license.getBlackIps())
                .createTime(license.getCreateTime()).updateTime(license.getUpdateTime()).build();
    }

    @Override
    public LicenseDetailResponse update(Integer id, LicenseParams entity) {
        License license = this.licenseRepository.findById(id).orElse(null);
        AssertUtil.checkNull(license, "授权码不存在");
        license.setLicenseName(entity.getLicenseName());
        license.setEnableState(entity.getEnableState());
        license.setEffectiveTime(entity.getEffectiveTime());
        license.setExpireTime(entity.getExpireTime());
        license.setWhiteIps(entity.getWhiteIps());
        license.setBlackIps(entity.getBlackIps());
        license.setNotes(entity.getNotes());
        license.setUpdateTime(new Date());
        this.licenseRepository.saveAndFlush(license);
        return this.selectOne(id);
    }


    @Override
    public ResultEntity<License> auth(String ip, String secretKey){
        License license = this.licenseRepository.findOne(
                Example.of(License.builder().licenseKey(secretKey).build())
        ).orElse(null);
        if(Objects.nonNull(license)){
            if(Objects.equals(1, license.getEnableState())){
                Session session = SessionManager.getSession(license.getId());
                if(Objects.nonNull(session)){
                    log.error("密钥已在线, secretKey: {}", secretKey);
                    return ResultEntity.error("密钥已在线", null);
                }
                return ResultEntity.success(license);
            }else{
                log.error("密钥被禁用, secretKey: {}", secretKey);
                return ResultEntity.error("密钥被禁用", null);
            }
        }
        return ResultEntity.error("密钥错误", null);
    }
}
